package com.cit.draw.redis;


import java.util.Set;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public interface PersistedCacheRequestHandler {

	/**
	 * Put Primitives Value into the cache without expiration.
	 * 
	 * Mention: Primitives are: boolean, any Numeric types and String.
	 * 
	 * @param entity
	 *            Must be Primitive, POJO should extends PersistedCacheObject,
	 *            see putPersistedCache(entity,key) for more details.
	 * @param key
	 *            The key of the Primitive
	 */
	<T> void putPrimitivePersistedCache(@Nonnull T entity, @Nonnull String key);

	/**
	 * Put Primitives Value into the cache without expiration. <br>
	 * Mention: Primitives are: boolean, any Numeric types and String.
	 * 
	 * @param entity
	 *            : Must be Primitive, POJO should extends PersistedCacheObject,
	 *            see putPersistedCache(entity,key) for more details.
	 * @param key
	 *            : The key of the Primitive
	 * @param expirationMinute
	 *            : The TTL of the target cached Object. After the expiration in
	 *            Minutes, the Primitive would automatically get removed from
	 *            the cache
	 */
	<T> void putPrimitivePersistedCache(@Nonnull T entity, @Nonnull String key,
			int expirationMinute);

	/**
	 * Get Primitives Value from the cache with the key as a String.As we won't
	 * know the type of the primitive, so I just simply return the String and
	 * please parse it to the format you suppose.
	 * 
	 * Mention: Primitives are: boolean, any Numeric types and String.
	 * 
	 * @param Key
	 *            The key of the Primitive
	 * 
	 * @return The target primitive we want to get
	 */
	String getPrimitivePersistedCache(@Nonnull String Key);

	/**
	 * Put value In Persisted Cache without Expiration.
	 * 
	 * Mention: All the POJO data use this method should extends
	 * PersistedCacheObject which is in the com.maaii.data.model.caching.caching
	 * package.
	 * 
	 * @param entity
	 *            : the Entity to caching
	 * 
	 * @param key
	 *            : the key of the caching record
	 * 
	 */
	<T extends PersistedCacheObject> void putPersistedCache(@Nonnull T entity,
			@Nonnull String key);

	/**
	 * Originally used in {@link FacebookContactAgent} to get the keys of a
	 * user's contact cache in order to invalidate all the user's cache record
	 * 
	 * @param username
	 *            : the name of the user
	 * @return Set: the keys of the user's record in cache. Used to invalidate
	 *         all the user's cache.
	 */
	@Nullable
	Set<String> getSetCache(@Nonnull String username);

	/**
	 * Originally used in {@link FacebookContactAgent} to store the keys of a
	 * user's contact cache. Put the list with the relevant username as the key 
	 * 
	 * @param username the key of the record 
	 * @param list the key list want to cache
	 */
	void putSetCache(@Nonnull String username, @Nonnull Set<String> list);

	/**
	 * Originally used in {@link FacebookContactAgent} to store the keys of a
	 * user's contact cache. Put the list with the relevant username as the key 
	 *  
	 * @param username the key of the record
	 * @param key the single key want to add
	 */
	void addCacheKeyIntoKeySet(@Nonnull String username, String key);

	/**
	 * Put value in Persisted Cache with expiration time.
	 * 
	 * Mention: All the POJO data use this method should extends
	 * PersistedCacheObject which is in the com.maaii.data.model.caching.caching
	 * package.
	 * 
	 * @param entity
	 *            The object we want to put in
	 * 
	 * @param key
	 *            The key of the object we want to put
	 * 
	 * @param expirationMinutes
	 *            The time to expire in minute. must be more than 0. If 0
	 *            occurred, it means to make it expire immediately
	 */
	<T extends PersistedCacheObject> void putPersistedCache(@Nonnull T entity,
			@Nonnull String key, int expirationMinutes);

	/**
	 * Get the Persisted Object in Cache with the key.
	 * 
	 * Mention: All the POJO data use this method should extends
	 * PersistedCacheObject which is in the com.maaii.data.model.caching
	 * package.
	 * 
	 * 
	 * @param key
	 *            The key of the target Object
	 * @return The target object we want to get
	 * 
	 */
	@Nullable
	<T extends PersistedCacheObject> T getPersistedCache(@Nonnull String key);

	/**
	 * Delete the record of the object with the key given in Cache
	 * 
	 * Mention: All the POJO data use this method should extends
	 * PersistedCacheObject which is in the com.maaii.data.model.caching
	 * package.
	 * 
	 * 
	 * @param key
	 *            The key of the object we want to delete
	 */
	<T extends PersistedCacheObject> void deletePersistedCache(
			@Nonnull String key);

	/**
	 * Increment the number stored at key by one. If the key does not exist or
	 * contains a value of a wrong type, set the key to the value of "0" before
	 * to perform the increment operation.
	 * 
	 * INCR commands are limited to 64 bit signed integers.
	 * 
	 * Note: this is actually a string operation, that is, in Redis there are
	 * not "integer" types. Simply the string stored at the key is parsed as a
	 * base 10 64 bit signed integer, incremented, and then converted back as a
	 * string.
	 * 
	 * Time complexity: O(1)
	 * 
	 * @param key
	 * @return this commands will reply with the new value of key after the
	 *         increment.
	 */
	Long increase(@Nonnull String key);

	/**
	 * 
	 * Decrement the number stored at key by one. If the key does not exist or
	 * contains a value of a wrong type, set the key to the value of "0" before
	 * to perform the decrement operation.
	 * 
	 * DECR commands are limited to 64 bit signed integers.
	 * 
	 * Note: this is actually a string operation, that is, in Redis there are
	 * not "integer" types. Simply the string stored at the key is parsed as a
	 * base 10 64 bit signed integer, incremented, and then converted back as a
	 * string.
	 * 
	 * @param key
	 * @return this commands will reply with the new value of key after the
	 *         Decrement.
	 */
	Long decrease(@Nonnull String key);

	/**
	 * Get the Long from the Key.If the key does not exist or contains a value
	 * of a wrong type, set the key to the value of "0" before to perform the
	 * increment operation.
	 * 
	 * Note: this is actually a string operation, that is, in Redis there are
	 * not "integer" types. Simply the string stored at the key is parsed as a
	 * base 10 64 bit signed integer, incremented, and then converted back as a
	 * string.
	 * 
	 * Time complexity: O(1)
	 * 
	 * @param key
	 * @return this commands will reply with the value of key.
	 */
	Long get(@Nonnull String key);

	/**
	 * This method would flush all the record in Redis. This is used in the test
	 * class in order to make cache fresh and without object conflict issues
	 * 
	 * Used to delete all current record or record in Redis.
	 */
	void flush();

	/**
	 * Set the cache record with the Long value given. If the key does not
	 * exist, a new key with this Long value would be put directly into the
	 * cache. Caution: this method won't make this record expired, so please
	 * take care of the life cycle of the record.
	 * 
	 * @param key
	 * @param value
	 */
	void set(@Nonnull String key, @Nonnull Long value);
}